﻿package jp.underthetree.air.deskclock 
{
	/**
	 * ...
	 * @author 
	 */
	public class GradientColorPicker
	{
		private var colors:Array;
		private var alphas:Array;
		private var points:Array;
		
		public function GradientColorPicker(colorTable:Array, alphaTable:Array = null, pointTable:Array = null) {
		
			colors = colorTable;
			alphas = alphaTable != null ? alphaTable : 
				colorTable.map(function (element:*, index:int, arr:Array):Number { return 1; } );
			points = pointTable != null ? pointTable : 
				colorTable.map(function (element:*, index:int, arr:Array):Number { return 1 / (colorTable.length - 1) * index; } );
		}
		
		public function getColor(pickPoint:Number):Number {
			var lIndex:int, rIndex:int;
			
			lIndex = this.pickLeftIndex(pickPoint);
			rIndex = this.pickRightIndex(pickPoint);
			
			return getPointFromLine(points[lIndex], colors[lIndex], points[rIndex], colors[rIndex], pickPoint);
		}
		
		public function getAlpha(pickPoint:Number):Number {
			var lIndex:int, rIndex:int;
			
			lIndex = this.pickLeftIndex(pickPoint);
			rIndex = this.pickRightIndex(pickPoint);
			
			var ex:Number = 1 / (points[rIndex] - points[lIndex]) * (pickPoint - points[lIndex]);
			var lRgb:Array = splitRGB(colors[lIndex]);
			var rRgb:Array = splitRGB(colors[rIndex]);
			var pRgb:Array = new Array();
			for (var i:int; i < lRgb.length; i ++ ) {
				pRgb.push(lRgb[i] + (rRgb[i] - lRgb[i]) * ex);
			}
			
			return makeColorCode(pRgb);
		}
		
		private function pickLeftIndex(pickPoint:Number):int {
			for (var i:int = 1; i < points.length - 1; i ++ ) {
				if (points[i] > pickPoint) {
					return i - 1;
				}
			}
			return points.length - 1;
		}
		
		private function pickRightIndex(pickPoint:Number):int {
			for (var i:int = points.length - 1; i > 0; i -- ) {
				if (points[i] < pickPoint) {
					return i + 1;
				}
			}
			return 0;
		}
		
		private function getPointFromLine(x1:Number, y1:Number, x2:Number, y2:Number, px:Number):Number {
			return (y1 + y2) / (x2 - x1) * (px - x1);
		}
		
		private function splitRGB(v:Number):Array {
			var a:Array = new Array();
			v = Math.floor(v);
			for (var i:int = 0; i < 3; i ++ ) {
				var col:Number = v % 256;
				a.unshift(col);
				v -= col;
				v /= 256;
			}
			return a;
		}
		
		private function makeColorCode(v:Array):Number {
			var col:Number = 0;
			v.forEach(function (el:*, index:int, ar:Array):void { col *= 256; col += Math.floor(el); } );
			return col;
		}
	}

}